#include "cybertron/license/License.hpp"
#include "cybertron/license/DongleInfo.hpp"
#include "cybertron/core/Log.hpp"
#include "cybertron/core/UtilTime.hpp"
#include <iostream>
#include <thread>
#include<vector>
#include<stdio.h>
//#if defined(WIN32) || defined(_WIN32)
//#define NODEFAULTLIB:LIBCMT

unsigned long SimOneLicense::CheckDog() {
	unsigned char bDataSec[sizeof(DongleInfo)];
	
	mDRet = Dongle_Enum(NULL, &mDCount);
	if (mDRet != DONGLE_SUCCESS)
	{
		logError("Enum Rockey ARM Failed! Return value: 0x%08X", mDCount);
		return mDRet;
	}
	
	std::vector<DONGLE_INFO> infoList;
	infoList.resize(mDCount);
	mDRet = Dongle_Enum(&infoList[0], &mDCount);
	if (mDRet != DONGLE_SUCCESS)
	{
		logError("Enum Rockey ARM Failed! Return value: 0x%08X", mDCount);
		return mDRet;
	}
	
	memcpy(&mCardDongleInfo, &infoList[0], sizeof(DONGLE_INFO));

	mDRet = Dongle_Open(&mhDongle, 0);
	//printf("Open Dongle ARM . Return value: 0x%08X \n", mDRet);
	if (mDRet != DONGLE_SUCCESS) {
		logError("Open Token Failed! Return value: %d", mDRet);
		return mDRet;
	}
	

	
	memset(bDataSec, 0, sizeof(DongleInfo));
	mDRet = Dongle_ReadData(mhDongle, 0, bDataSec, sizeof(DongleInfo));
	//printf("Read data section. Return : 0x%08X . \n", mDRet);
	if (DONGLE_SUCCESS != mDRet)
	{
		return mDRet;
	}

	memcpy(&mDongleInfo, bDataSec, sizeof(DongleInfo));
	logInfo("product type is %s", mDongleInfo.product_type);
	logInfo("channel name is %s", mDongleInfo.channel_name);
	//logInfo("product code is %d", mDongleInfo.product_code);
	logInfo("version is %s", mDongleInfo.version);

	bool isHasPower = false;
	mDRet = Dongle_GetUTCTime(mhDongle, &mDUTCTime);
	if (mDRet != DONGLE_SUCCESS){
		logError("Can not get UTC time");
		return mDRet;
	}
	if (mDUTCTime == 0) {
		isHasPower = false;
	}
	else {
		isHasPower = true;
	}
	mDRet = Dongle_GetDeadline(mhDongle, &mDDeadTime);
	if (mDRet != DONGLE_SUCCESS){
		logError("Can not get dead time");
		return mDRet;
	}
	logInfo("===================>dog admin pin pwd :%s <===========================", (char*)mAdminPin.c_str());
	if (isHasPower) {
		mDRet = Dongle_VerifyPIN(mhDongle, FLAG_USERPIN, (char*)mAdminPin.c_str(), &mRemainCount);
		//printf("Verify Admin PIN. Return: 0x%08X\n", mDRet);
		if (mDRet != DONGLE_SUCCESS) {
			logError("Verify User PIN Failed! Return value: 0x%08X", mDCount);
			return mDRet;
		}
	}
	else {
		mDUTCTime = cybertron::UtilTime::getTimeStampSeconds();
		if (mDDeadTime < mDUTCTime) {
			logError("License is Overdue.");
			return DONGLE_CLOCK_EXPIRE;
		}
	}

	int year, mon, day, hour, min, sec;
	time_t tm = (time_t)mDDeadTime;
	struct tm *ptm = gmtime(&tm);
	year = ptm->tm_year + 1900;
	mon = ptm->tm_mon + 1;
	day = ptm->tm_mday;
	hour = ptm->tm_hour;
	min = ptm->tm_min;
	sec = ptm->tm_sec;
	mDDeadTimeStr = std::to_string(year) + '-' + std::to_string(mon) + '-' + std::to_string(day);

	mDRet = Dongle_Close(mhDongle);
	logInfo("Close Dongle ARM . Return value: 0x%08X", mDRet);
	mDongleExist = true;
	mDongleThreadRunning = true;


	return DONGLE_SUCCESS;
}


void SimOneLicense::GenerateThread() {
	DONGLE_HANDLE mphDongle;
	int mpDCount = 0;
	int mpRemainCount = 0;
	int mpDRet = Dongle_Enum(NULL, &mDCount);
	if (mpDRet != DONGLE_SUCCESS)
	{
		mDongleExist = false;
		return;
	}

	mpDRet = Dongle_Open(&mphDongle, 0);
	if (mpDRet != DONGLE_SUCCESS)
	{
		mDongleExist = false;
		return;
	}

	while (mDongleThreadRunning)
	{
		mpDRet = Dongle_VerifyPIN(mphDongle, FLAG_USERPIN, (char*)mAdminPin.c_str(), &mRemainCount);
		if (mpDRet != DONGLE_SUCCESS) {
			mDongleExist = false;
			break;
		}
		std::this_thread::sleep_for(std::chrono::seconds(5));
	}
	mpDRet = Dongle_Close(mphDongle);
}
//#endif
//////////////////////////////////////////////////////////////
SimOneLicense::SimOneLicense(){
	mDongle = DONGLE_SETTING;
	mDRet = 0;
	mDCount = 0;
	mDUTCTime = 0;
	mDDeadTime = 0;
	mhDongle = nullptr;
	
	
	mRemainCount = 0;
	mDongleExist = false;
	mDongleThreadRunning = false;
	mAdminPin = ADMINPIN;
	memset(&mDongleInfo,0, sizeof(DongleInfo));
	memset(&mCardDongleInfo, 0, sizeof(DONGLE_INFO));
	//mImpl.reset(new LicenseImpl());
}

unsigned long SimOneLicense::InitDog(){
//	mDongle = true;
	if(mDongle){
		unsigned long ret = CheckDog();
		//std::thread t1(&SimOneLicense::GenerateThread, this);
		//t1.detach();
		return ret;
	} else {
		return DONGLE_SUCCESS;
	}
}
bool SimOneLicense::IsUserDog() {
	return mDongle;
}
bool SimOneLicense::getDongleExist(){
	if(mDongle){
		DONGLE_HANDLE mphDongle;
		int mpDCount = 0;
		int mpRemainCount = 0;
		int mpDRet = Dongle_Enum(NULL, &mDCount);
		if (mpDRet != DONGLE_SUCCESS)
		{
			mDongleExist = false;
			return false;
		}

		mpDRet = Dongle_Open(&mphDongle, 0);
		if (mpDRet != DONGLE_SUCCESS)
		{
			mDongleExist = false;
			return false;
		}

		while (mDongleThreadRunning)
		{
			mpDRet = Dongle_VerifyPIN(mphDongle, FLAG_USERPIN, (char*)mAdminPin.c_str(), &mRemainCount);
			if (mpDRet != DONGLE_SUCCESS) {
				mDongleExist = false;
				break;
			}
			std::this_thread::sleep_for(std::chrono::seconds(5));
		}
		mpDRet = Dongle_Close(mphDongle);		
		return mDongleExist;
	} else {
		return true;
	}
}

void SimOneLicense::StopDongleThread(){
	if(mDongle){
		logWarning("dongle recive stop.");
		//mImpl->StopDongleThread();
		mDongleThreadRunning = false;
	}
}


SimOneLicense::~SimOneLicense(){

}
